package com.aps.server.parse.service;

import com.aps.server.parse.model.ExcelColumnConfig;
import com.aps.server.parse.model.ExcelImportResult;
import com.aps.server.parse.model.ExcelParseValidate;
import com.aps.server.parse.utils.ExcelParserUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.*;

/**
 * @Author nbZhuozh
 * @Date 2025-09-01  15:53
 **/
@Slf4j
@Service
public class ExcelParserService {

    /**
     * 默认 导出模板
     */
    public byte[] exportTemplate(Class<?> targetClazz , String sheetName){
        //获取表头内容
        List<ExcelColumnConfig> excelColumnConfigs = ExcelParserUtil.getExcelColumnConfigs(targetClazz);
        if(CollectionUtils.isEmpty(excelColumnConfigs)){
            return new byte[0];
        }
        try(Workbook wb = new XSSFWorkbook();
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream())
        {
            Sheet sheet = wb.createSheet(StringUtils.isEmpty(sheetName) ? "导入数据模板" : sheetName);
            int columns = excelColumnConfigs.size();
            CellStyle headerStyle = createHeaderStyle(wb);
            CellStyle dataStyle= createDataStyle(wb);
            //draw headers
            Row headerRow = sheet.createRow(0);
            for (int i = 0; i < columns; i++) {
                Cell cell = headerRow.createCell(i);
                cell.setCellValue(excelColumnConfigs.get(i).getLabel());
                cell.setCellStyle(headerStyle);
                sheet.setColumnWidth(i, 4000);
            }
            // create sample data
            Row sampleRow = sheet.createRow(1);
            for (int i = 0; i < columns; i++) {
                Cell cell = sampleRow.createCell(i);
                cell.setCellValue(excelColumnConfigs.get(i).getSampleValue());
                cell.setCellStyle(dataStyle);
            }
            wb.write(outputStream);
            return outputStream.toByteArray();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 数据录入
     * todo 上传文件 可做可不做当前
     * @param file
     * @param targetClazz
     * @return
     */
    public <T> ExcelImportResult importFile(MultipartFile file , Class<T> targetClazz) throws IOException {
        //构造result
        ExcelImportResult excelImportResult = ExcelImportResult.create(file, targetClazz);
        //读取
        List<T> dataList = read(file, targetClazz);
        if(dataList == null){
            dataList = new ArrayList<>();
        }
        excelImportResult.setReadSize(dataList.size());
        //校验  返回errorList
        validate(dataList,excelImportResult);
        log.info("============================generic - excel:导入数据长度：{}",dataList.size());
        log.info("============================generic - excel:数据集：{}",dataList.toString());
        //构造result
        if(dataList.isEmpty()){
            excelImportResult.setErrorExcelDetailsMsg("未读取到有效数据");
        }
        return excelImportResult;
    }


    /**
     * 自定义校验规则 , 修改 excelImport结果
     */
    public <T> void validate(List<T> dataList , ExcelImportResult excelImportResult){
        List<String> errorMsgList = new ArrayList<>();
        List<T> errDataList = new ArrayList<>();
        for (int i = 0; i < dataList.size(); i++) {
            T data = dataList.get(i);
            Class<?>[] interfaces = data.getClass().getInterfaces();
            boolean assign = interfaces.length >0
                    && Arrays.asList(data.getClass().getInterfaces()).contains(ExcelParseValidate.class);
            if (assign) {
                 ExcelParseValidate excelParseValidate = (ExcelParseValidate) data;
                boolean validate = excelParseValidate.validate();
                if(!validate){
                    String rowErrorDetails = excelParseValidate.createRowErrorDetails(data, i + 1);
                    errorMsgList.add(rowErrorDetails);
                    errDataList.add(data);
                }
            }
        }
        excelImportResult.setErrorSize(errDataList.size());
        excelImportResult.setErrorList(errDataList);
        excelImportResult.setSuccessSize(dataList.size() - errDataList.size());
        excelImportResult.setErrorExcelDetailsMsg(StringUtils.isEmpty(errorMsgList) ? "" : org.apache.commons.lang3.StringUtils.join(errorMsgList, "\n"));
    }



    /**
     * 读取数据
     * @param file
     * @param targetClazz
     * @return
     */
    public <T> List<T> read(MultipartFile file , Class<T> targetClazz){
        return ExcelParserUtil.convertToClass(targetClazz, readToMap(file, targetClazz));
    }


    private List<Map<String,Object>> readToMap(MultipartFile file , Class<?> targetClazz){
        if(targetClazz == null){
            return Collections.emptyList();
        }
        try(Workbook wb = new XSSFWorkbook(file.getInputStream())){
            // 解析Excel文件
            Sheet sheet = wb.getSheetAt(0);
            // 解析表头映射
            Map<String, String> headerMapping = ExcelParserUtil.parseHeaderMapping(sheet, targetClazz);
            // 读取数据
            return ExcelParserUtil.parseExcelMapping(sheet, headerMapping);

        } catch (Exception e){
            log.error("[error parsing with ->]" + targetClazz.toGenericString(), e);
            return Collections.emptyList();
        }
    }

    /**
     * 创建表头样式
     */
    private CellStyle createHeaderStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);

        Font font = workbook.createFont();
        font.setBold(true);
        font.setFontHeightInPoints((short) 12);
        style.setFont(font);
        return style;
    }

    /**
     * 创建数据样式
     */
    private CellStyle createDataStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        style.setAlignment(HorizontalAlignment.LEFT);
        style.setVerticalAlignment(VerticalAlignment.CENTER);

        return style;
    }

}
